package kr.re.etri.snsenabler.server;

import java.util.logging.Level;
import java.util.logging.Logger;

import kr.re.etri.snsenabler.client.service.FacebookService;
import kr.re.etri.snsenabler.shared.Data;
import kr.re.etri.snsenabler.shared.LoginProperties;
import kr.re.etri.snsenabler.shared.ServiceResponse;
import kr.re.etri.snsenabler.shared.SocialServiceProperties;
import kr.re.etri.snsenabler.shared.SocialServiceProvider;

import org.json.simple.JSONObject;
import org.json.simple.JSONValue;
import org.scribe.builder.api.Api;
import org.scribe.builder.api.FacebookApi;
import org.scribe.model.OAuthRequest;
import org.scribe.model.Response;
import org.scribe.model.Token;
import org.scribe.model.Verb;
import org.scribe.model.Verifier;

public class FacebookServiceImpl extends AbstractSocialServiceServlet implements FacebookService {

	private Logger logger = Logger.getLogger(FacebookServiceImpl.class.getName());
	private static final String CONSUMER_KEY = "376802872342970";;
	private static final String CONSUMER_SECRET = "8058aa1444c763c9f5725df3a484234b";
	private static final Token EMPTY_TOKEN = null;
	private static final String USER_INFO_1_URL = "https://graph.facebook.com/me";
	private static final String USER_INFO_2_URL = "https://graph.facebook.com/";

	@Override
	protected Class<? extends Api> getApi() {
		return FacebookApi.class;
	}

	@Override
	protected String getConsumerKey() {
		return CONSUMER_KEY;
	}

	@Override
	protected String getConsumerSecret() {
		return CONSUMER_SECRET;
	}

	@Override
	public ServiceResponse fetchAuthorizationUrl(SocialServiceProvider provider) {
		logger.info("=== Facebook's OAuth Workflow ===");
		String authorizationUrl = getService(provider).getAuthorizationUrl(EMPTY_TOKEN);
		logger.info("Authorize here: " + authorizationUrl);

		Data data = new Data();
		data.put(Data.KEY_1, authorizationUrl);
		ServiceResponse response = new ServiceResponse(data);
		return response;
	}

	@Override
	public ServiceResponse sendVerifier(Data loginData, SocialServiceProvider provider, String verifier) {
		logger.info("Verifier: " + verifier);

		logger.info("Trading the Request Token for an Access Token...");
		Token accessToken = getService(provider).getAccessToken(EMPTY_TOKEN, new Verifier(verifier));
		logger.info("Got the Access Token: " + accessToken);

		logger.info("Getting account/verify_credentials...");
		OAuthRequest request = new OAuthRequest(Verb.GET, USER_INFO_1_URL);
		getService(provider).signRequest(accessToken, request);
		Response response = request.send();
		logger.info("What we got: ");
		logger.info(String.valueOf(response.getCode()));
		logger.info(response.getBody());

		JSONObject jsonObject = (JSONObject)JSONValue.parse(response.getBody());
		String id = jsonObject.get("id").toString();
		logger.info("ID: " + id);
		request = new OAuthRequest(Verb.GET, USER_INFO_2_URL + id);
		getService(provider).signRequest(accessToken, request);
		response = request.send();
		logger.info("What we got: ");
		logger.info(String.valueOf(response.getCode()));
		logger.info(response.getBody());

// {"id":"100003625378801","name":"\ucd5c\uae30\uc12d","first_name":"\uae30\uc12d","last_name":"\ucd5c","link":"http:\/\/www.facebook.com\/profile.php?id=100003625378801","education":[{"school":{"id":"126403430768688","name":"\ub3d9\uad6d\ub300"},"year":{"id":"144503378895008","name":"1999"},"concentration":[{"id":"201989123149739","name":"\uc804\uc790\uacc4\uc0b0"}],"type":"College"}],"gender":"male","timezone":9,"locale":"ko_KR","verified":true,"updated_time":"2012-03-21T05:53:23+0000"}		

		try {
			Data userData = new Data();
			userData.put(SocialServiceProperties.LOGIN_ID, loginData.get(LoginProperties.LOGIN_ID));
			userData.put(SocialServiceProperties.SERVICE_PROVIDER, provider.getName());
			userData.put(SocialServiceProperties.USER_ID, id);
			userData.put(SocialServiceProperties.ACCESS_TOKEN, accessToken.getToken());
			getDbService().insertOAuthSocialService(userData);
			return new ServiceResponse(userData);
		} catch (Exception e) {
			logger.log(Level.SEVERE, e.getMessage(), e);
			return new ServiceResponse(e.getMessage());
		}
	}
}
